﻿using Engine;
using Engine.Audio;
using Engine.Graphics;
using Game;
using GameEntitySystem;
using Jint.Native;
using SAGhoul.Blocks;
using System;
using System.Collections.Generic;
using System.Linq;
using TemplatesDatabase;

namespace SAGhoul
{
	public class ComponentSAGPlayer : Component, IUpdateable, IDrawable
	{
		public static float BGMFadeOutDuration => 5f;
		public SubsystemSky m_subsystemSky;
		public SubsystemTerrain m_subsystemTerrain;
		public SubsystemBodies m_subsystemBodies;
		public SubsystemTimeOfDay m_subsystemTimeOfDay;
		public SubsystemGameInfo m_subsystemGameInfo;
		public SubsystemSAG m_subsystemSAG;
		public SubsystemPickables m_subsystemPickables;
		public SubsystemSAGArtifactBlockBehavior m_subsystemSAGArtifactBlockBehavior;
		public SubsystemAudio m_subsystemAudio;
		public SubsystemTime m_subsystemTime;
		public ComponentPlayer m_componentPlayer;
		public ComponentScreenOverlays m_componentScreenOverlays;
		public UpdateOrder UpdateOrder => UpdateOrder.Default;
		public int[] DrawOrders => [1101];

		public float SpawnCd;
		public float SoulsValue;
		public float ExplodeSwayPower;
		public float ExplodeSwayT;

		readonly Game.Random m_random = new();
		readonly PrimitivesRenderer3D m_primitivesRenderer3D = new();

		LabelWidget LabelWidget;
		Sound m_bgmSound;
		float m_lastSkyLightIntensity;
		float? m_bgmStopTime;//null表示正在播放，0表示没有播放，否则表示正在淡出
		float m_bgmStartCd;//防止bgm立刻播放覆盖鼓声
		bool m_bossLiving;
		bool m_initialized;
		bool m_shouldPlayExpAudio;
		bool m_bossSpawned;
		bool m_lastIsArtifactRunning;

		public override void Load(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap)
		{
			base.Load(valuesDictionary, idToEntityMap);
			m_subsystemSky = Project.FindSubsystem<SubsystemSky>(throwOnError: true);
			m_subsystemTerrain = Project.FindSubsystem<SubsystemTerrain>(throwOnError: true);
			m_subsystemBodies = Project.FindSubsystem<SubsystemBodies>(throwOnError: true);
			m_subsystemGameInfo = Project.FindSubsystem<SubsystemGameInfo>(throwOnError: true);
			m_subsystemTimeOfDay = Project.FindSubsystem<SubsystemTimeOfDay>(throwOnError: true);
			m_subsystemSAG = Project.FindSubsystem<SubsystemSAG>(throwOnError: true);
			m_subsystemPickables = Project.FindSubsystem<SubsystemPickables>(throwOnError: true);
			m_subsystemSAGArtifactBlockBehavior = Project.FindSubsystem<SubsystemSAGArtifactBlockBehavior>(throwOnError: true);
			m_subsystemAudio = Project.FindSubsystem<SubsystemAudio>(throwOnError: true);
			m_subsystemTime = Project.FindSubsystem<SubsystemTime>(throwOnError: true);
			m_componentPlayer = Entity.FindComponent<ComponentPlayer>(throwOnError: true);
			m_componentScreenOverlays = Entity.FindComponent<ComponentScreenOverlays>(throwOnError: true);
			LabelWidget = new LabelWidget()
			{
				DropShadow = true,
				FontScale = 0.8f,
				Margin = new Vector2(5f, 0f),
				IsHitTestVisible = false,
				TextAnchor = TextAnchor.HorizontalCenter,
				HorizontalAlignment = WidgetAlignment.Far,
				VerticalAlignment = WidgetAlignment.Center
			};
			m_initialized = false;
			SpawnCd = valuesDictionary.GetValue<float>("SpawnCd");
			SoulsValue = valuesDictionary.GetValue<float>("SoulsValue");
			m_bossSpawned = valuesDictionary.GetValue<bool>("m_bossSpawned");
		}
		public override void Save(ValuesDictionary valuesDictionary, EntityToIdMap entityToIdMap)
		{
			base.Save(valuesDictionary, entityToIdMap);
			valuesDictionary.SetValue("SpawnCd", SpawnCd);
			valuesDictionary.SetValue("SoulsValue", SoulsValue);
			valuesDictionary.SetValue("m_bossSpawned", m_bossSpawned);
		}
		public override void OnEntityRemoved()
		{
			base.OnEntityRemoved();
			m_componentPlayer.GameWidget.Children.Find<CanvasWidget>("ControlsContainer").RemoveChildren(LabelWidget);
		}
		public void Initialize()
		{
			m_componentPlayer.GameWidget.Children.Find<CanvasWidget>("ControlsContainer").AddChildren(LabelWidget);
			m_initialized = true;
		}
		public void Update(float dt)
		{//同时存在100只普通僵尸是没问题的，月食晚间大概660秒
			if (!m_initialized)
				Initialize();
			if (SoulsValue >= 1)
			{
				SoulsValue = 0;
				m_componentPlayer.ComponentMiner.ComponentCreature.ComponentHealth.Injure(1f, null, true, this.Lang("SoulAttacksAccumulation"));
			}
			else
			{
				SoulsValue = MathUtils.Clamp(SoulsValue - dt / 300f, 0f, 1f);
			}

			ExplodeSwayT = MathUtils.Max(ExplodeSwayT - dt, 0);
			float sway = 0.001f * MathUtils.Sin(50f * ExplodeSwayT) * ExplodeSwayT * ExplodeSwayPower;
			if (sway != 0)
				m_componentPlayer.ComponentMiner.ComponentCreature.ComponentLocomotion.LookAngles += new Vector2(sway);
			double daysCount = SAGhoulsManager.GetDaysCount(m_subsystemGameInfo, m_subsystemTimeOfDay);
			int period = SAGhoulsManager.GetPeriod(daysCount);
			float skyLightIntensity = m_subsystemSky.SkyLightIntensity;
			bool duringEclipse = SAGhoulsManager.IsDuringBloodMoon(m_subsystemSAG);
			bool isEclipseDay = SAGhoulsManager.IsBloodMoonDay(m_subsystemSAG);
			if (isEclipseDay)
			{
				m_componentPlayer.ComponentVitalStats.Sleep = 1f;//锁定疲劳值让玩家无法入睡
				if (duringEclipse)
				{
					SpawnCd -= dt;
					if (SpawnCd <= 0)
					{
						//Log.Warning(SubsystemSAG.BossData.ContainsKey(period));
						if (skyLightIntensity <= 0.1f && skyLightIntensity > m_lastSkyLightIntensity && !m_bossSpawned && m_subsystemSAG.BossData.TryGetValue(period, out string value))
						{//boss刷新
						 //Log.Warning(period);
							SpawnBoss(value);
							SpawnCd = 20f;
							m_bossSpawned = true;
						}
						else
						{//小怪刷新
							var array = new DynamicArray<ComponentBody>();
							m_subsystemBodies.FindBodiesAroundPoint(m_componentPlayer.ComponentBody.Position.XZ, MaxSpawnRange, array);
							int maxCount = 75;
							float speed = 1f;
							switch (m_subsystemSAG.Difficulty)
							{
								case Difficulty.VeryEasy: maxCount = 30; speed = 0.33f; break;
								case Difficulty.Easy: maxCount = 50; speed = 0.75f; break;
								case Difficulty.Hard: maxCount = 100; speed = 1.5f; break;
								case Difficulty.VeryHard: maxCount = 125; speed = 3f; break;
							}
							if (array.Count(item => item.Entity.FindComponent<ComponentSAGhouls>() != null) < maxCount)
							{
								Vector3 position = ScoreSpawnPosition();
								Spawn(GetSpawnEntityName(), position);
								SpawnCd = MathUtils.Clamp(m_subsystemSky.SkyLightIntensity, 0.1f, 0.75f) * 20f / speed;//2-15秒刷新一只
							}
						}
					}
					if (m_componentPlayer.ComponentSleep.IsSleeping)
					{
						m_componentPlayer.ComponentSleep.WakeUp();//若月食晚间玩家在睡觉，强制苏醒
					}
				}
			}
			if (!duringEclipse)
			{
				if (daysCount >= 64 && IntervalUtils.IsBetween(m_subsystemTimeOfDay.TimeOfDay, m_subsystemTimeOfDay.DuskStart, m_subsystemTimeOfDay.DawnStart) && m_subsystemSAG.SAGEnable && m_subsystemSAG.m_subsystemTartareosity.WorldType == Tartareosity.WorldType.Default)
				{
					SpawnCd -= dt;
					if (SpawnCd <= 0)
					{
						var array = new DynamicArray<ComponentBody>();
						m_subsystemBodies.FindBodiesAroundPoint(m_componentPlayer.ComponentBody.Position.XZ, MaxSpawnRange, array);
						if (array.Count(item => item.Entity.FindComponent<ComponentSAGhouls>() != null) < 30)
						{
							Vector3 position = ScoreSpawnPosition();
							Spawn(GetSpawnEntityName(), position);
							SpawnCd = MathUtils.Clamp(m_subsystemSky.SkyLightIntensity, 0.1f, 0.4f) * 40f;//刷新时间10-90秒
						}
					}
				}//加上了平时也会刷怪的行为
				else
				{
					SpawnCd = 10f;
				}
				m_bossSpawned = false;
			}
			int activeBlockIndex = Terrain.ExtractContents(m_componentPlayer.ComponentMiner.ActiveBlockValue);
			if (activeBlockIndex == typeof(SAGArtifactBlock).BlockIndex())
			{
				Block block = BlocksManager.Blocks[activeBlockIndex];
				int durability = block.GetDurability(m_componentPlayer.ComponentMiner.ActiveBlockValue);
				int currentDamage = block.GetDamage(m_componentPlayer.ComponentMiner.ActiveBlockValue);
				float radius = m_subsystemSAGArtifactBlockBehavior.Range_Radius;
				float rangeUp = m_subsystemSAGArtifactBlockBehavior.Range_Up;
				float rangeDown = m_subsystemSAGArtifactBlockBehavior.Range_Down;
				Vector3 center = m_componentPlayer.ComponentBody.BoundingBox.Center();
				double totalElapsedGameTime = m_subsystemGameInfo.TotalElapsedGameTime;
				foreach (Pickable pickable in m_subsystemPickables.Pickables)
				{
					if (totalElapsedGameTime - pickable.CreationTime <= 1)//掉落物产生1秒后再吸引，防止刚爆出来就吸导致经验球全叠在一起看上去像只有一个
						continue;
					//if (pickable.FlyToPosition.HasValue)
					//	continue;//由于flyToPosition是center，而玩家位置是会变化的，所以这个也应该实时变化
					float distanceSquared = Vector3.DistanceSquared(pickable.Position, center);
					float deltaY = center.Y - pickable.Position.Y;
					if (Vector2.DistanceSquared(pickable.Position.XZ, center.XZ) > radius * radius || deltaY > rangeDown || deltaY < -rangeUp || distanceSquared < 2.25f)
						continue;
					int id = Terrain.ExtractContents(pickable.Value);
					if (id == typeof(ExperienceBlock).BlockIndex() || id == typeof(BizarreMetalBlock).BlockIndex() || id == typeof(SoulsResidueBlock).BlockIndex() || id == typeof(LargeSoulsResidueBlock).BlockIndex() || id == typeof(SAGArtifactBlock).BlockIndex() || id == typeof(SAGBrokenArtifactBlock).BlockIndex())
					{
						if (currentDamage > 0 && id == typeof(ExperienceBlock).BlockIndex() && distanceSquared <= 6.25f)
						{//经验修补
							pickable.ToRemove = true;
							int newDamage = currentDamage - 1;
							int newValue = block.SetDamage(m_componentPlayer.ComponentMiner.ActiveBlockValue, newDamage);
							m_componentPlayer.ComponentMiner.RemoveActiveTool(1);
							m_componentPlayer.ComponentMiner.Inventory.AddSlotItems(m_componentPlayer.ComponentMiner.Inventory.ActiveSlotIndex, newValue, 1);
							m_shouldPlayExpAudio = true;
							continue;
						}
						pickable.FlyToPosition = center;
					}
				}
			}
			if (m_subsystemTime.PeriodicGameTimeEvent(0.5, 0) && m_shouldPlayExpAudio)
			{
				m_subsystemAudio.PlaySound("Audio/Artifact/Artifact_ExpCollect", 3f, -0.2f, 0f, 0f);
				m_shouldPlayExpAudio = false;
			}
			if (activeBlockIndex == typeof(SAGArtifactBlock).BlockIndex())
			{
				bool isArtifactRunning = m_subsystemSAGArtifactBlockBehavior.IsRunning;
				if (!isArtifactRunning && m_lastIsArtifactRunning)
				{
					m_subsystemAudio.PlaySound("Audio/Artifact/Artifact_Ready", 3f, -0.2f, 0f, 0f);
				}
				m_lastIsArtifactRunning = isArtifactRunning;
			}
			m_lastSkyLightIntensity = skyLightIntensity;

			LabelWidget.IsVisible = m_subsystemSAG.SAGEnable && m_subsystemSAG.m_subsystemTartareosity.WorldType == Tartareosity.WorldType.Default;
			string dayText = this.Lang("Day");
			string line1, line2;
			if (duringEclipse)
			{
				line1 = $"{daysCount:0.0}{dayText}\n";
				line2 = this.Lang("TheyComing");
			}
			else
			{// 计算离下次血月的天数：
				int completedPeriod = daysCount < SAGhoulsManager.BloodMoonPeriodLength ? 0 : period;
				bool beforePeriod = isEclipseDay && m_subsystemTimeOfDay.CalculateTimeOfDay(m_subsystemGameInfo.TotalElapsedGameTime) > m_subsystemTimeOfDay.Midday;//血月当天的白天
				// - 若今天就是血月日（SAGhoulsManager.IsBloodMoonDay == true），返回 0。
				// - 否则向前模拟若干天（最多查找两倍周期长度）并根据当前月相与天数规则寻找下一个既满足“异常月相(0 或 4)”又满足“周期边界（Ceiling(day - DayStart) % BloodMoonPeriodLength == 0）”的日子。
				// - 若模拟未找到（极端情况），退回到以周期边界为准的保底计算。
				int day2;
				if (isEclipseDay)
				{
					day2 = 0;
				}
				else
				{
					int maxLookAhead = SAGhoulsManager.BloodMoonPeriodLength * 2;
					day2 = maxLookAhead;
					int currentMoonPhase = m_subsystemSky.MoonPhase;
					double currentDayValue = m_subsystemTimeOfDay.Day - m_subsystemTimeOfDay.DayStart; // 与 IsBloodMoonDay 中使用的一致
					for (int n = 1; n <= maxLookAhead; n++)
					{
						int futureMoonPhase = (currentMoonPhase + n) % 8;
						int futureDayIndex = (int)MathUtils.Ceiling(currentDayValue + n);
						if ((futureMoonPhase == 0 || futureMoonPhase == 4) && futureDayIndex % SAGhoulsManager.BloodMoonPeriodLength == 0)
						{
							day2 = n;
							break;
						}
					}
					if (day2 == maxLookAhead)
					{// 保底：如果模拟没有找到（极端情况），使用基于周期边界的计算
						double nextBoundary = MathUtils.Ceiling(daysCount / SAGhoulsManager.BloodMoonPeriodLength) * SAGhoulsManager.BloodMoonPeriodLength;
						day2 = (int)Math.Ceiling(Math.Max(0.0, nextBoundary - daysCount));
						if (day2 == 0)
							day2 = SAGhoulsManager.BloodMoonPeriodLength;
					}
				}
				line1 = $"{completedPeriod}/{SAGhoulsManager.MaxPeriodCount}  {daysCount:0.0}{dayText}\n";
				line2 = $"{this.Lang("Countdown")}{day2}{dayText}";
				//line2 = $"MoonPhase{m_subsystemSky.MoonPhase} {dayText}{m_subsystemSAG.m_subsystemTimeOfDay.Day - m_subsystemSAG.m_subsystemTimeOfDay.DayStart:0.0}";
			}
			LabelWidget.Text = line1 + line2;

			m_bgmStartCd = MathUtils.Max(0f, m_bgmStartCd - dt);
			if (m_bgmStopTime.HasValue)
			{//更新淡出时间
				m_bgmStopTime = MathUtils.Max(0f, m_bgmStopTime.Value - dt);
			}
			else if (!m_bossLiving)
			{//若没有boss存活则淡出bgm
				StopBgm();
			}
			if (m_bgmSound != null)
			{//播放bgm
				float volume = 1f;
				if (m_bgmSound.Volume > AudioManager.MinAudibleVolume && (m_bgmStopTime ?? 1f) > 0f)
				{
					m_bgmSound.Play();
					if (m_bgmStopTime.HasValue)
					{//淡出
						volume = m_bgmStopTime.Value / BGMFadeOutDuration;
					}
				}
				else
				{
					m_bgmSound.Pause();
				}
				m_bgmSound.Volume = MathUtils.Clamp((SettingsManager.MusicVolume + SettingsManager.SoundsVolume) * 0.5f, 0f, 1f) * volume;
			}
			else if (m_bossLiving && m_bgmStartCd <= 0f)
			{//若有boss但无bgm，则重新播放
				PlayBgm("Audio/bgm/" + m_random.Int(1, 4).ToString());
			}
			m_bossLiving = false;
		}
		public override void Dispose()
		{
			Utilities.Dispose(ref m_bgmSound);
		}

		public static float MinSpawnRange => 18f;
		public static float MaxSpawnRange => MathUtils.Clamp(48f, 37f, MathUtils.Min(40f, SettingsManager.VisibilityRange * 0.8f));//生物超出摄像机52格距离就会释放

		public Vector3 ScoreSpawnPosition()
		{
			Vector2 playerV2 = m_componentPlayer.ComponentBody.Position.XZ;
			Vector2 playerBackV2 = Vector2.Normalize((-m_componentPlayer.ComponentBody.Matrix.Forward).XZ);
			Vector2 v2;
			do
			{
				v2 = playerV2 + m_random.Vector2(MinSpawnRange, MaxSpawnRange);
			}
			while (MathUtils.Abs(SAGhoulsManager.GetAngleByVector(playerBackV2, Vector2.Normalize(v2 - playerV2))) > MathUtils.DegToRad(30f));
			Point2 p2 = Terrain.ToCell(v2);
			int topHeight = m_subsystemTerrain.Terrain.GetTopHeight(p2.X, p2.Y);
			return new Vector3(p2.X, topHeight, p2.Y) + new Vector3(m_random.Float(-0.5f, 0.5f), m_random.Float(0, 0.2f), m_random.Float(-0.5f, 0.5f));
		}
		public string GetSpawnEntityName()
		{
			double daysCount = SAGhoulsManager.GetDaysCount(m_subsystemGameInfo, m_subsystemTimeOfDay);
			int period = SAGhoulsManager.GetPeriod(daysCount);
			//Log.Warning(period);
			Dictionary<int, string> dictionary = SAGhoulsManager.Periods[period - 1];
			if (dictionary.Count <= 0)
				return string.Empty;
			else if (dictionary.Count == 1)
			{
				return dictionary.Values.ToArray()[0];
			}
			int weight = m_random.Int(0, 100);
			for (int i = 0; i < dictionary.Count; i++)
			{
				int[] keys = [.. dictionary.Keys];
				int key = keys[i];
				int last = i > 0 ? keys[i - 1] : 0;
				if (weight < key && weight >= last)
				{
					return dictionary[key];
				}
			}
			return string.Empty;
		}
		public void Spawn(string entityName, Vector3 position, float spawnDuration = 0, bool isBoss = false)
		{
			Entity entity = DatabaseManager.CreateEntity(Project, entityName, throwIfNotFound: false);
			if (entity != null)
			{
				if (spawnDuration > 0)
				{
					entity.FindComponent<ComponentSpawn>()?.SpawnDuration = spawnDuration;
				}
				ComponentSAGhouls componentSAGhouls = entity.FindComponent<ComponentSAGhouls>();
				if (componentSAGhouls != null)
				{
					componentSAGhouls.m_componentCreature.ComponentBody.Position = position;
					//componentSAGhouls.m_componentChaseBehavior.Attack(m_componentPlayer.ComponentMiner.ComponentCreature, MaxSpawnRange * 1.25f, float.MaxValue, true);
					componentSAGhouls.PersistentAttack = true;
					componentSAGhouls.IsBoss = isBoss;
				}
				Project.AddEntity(entity);
			}
		}
		public void SpawnBoss(string entityName)
		{
			Vector3 position = ScoreSpawnPosition();
			if (entityName == "SAGhoul_NecroDrift")
				position += 24f * Vector3.UnitY;
			Spawn(entityName, position, 6f, true);
			string audio0 = "Audio/bgm/0", bgm = "Audio/bgm/" + m_random.Int(1, 4).ToString();
			m_subsystemAudio.PlaySound(audio0, 1f, 0f, 0f, 0f);
			for (int i = 1; i <= 2; i++)
			{
				Time.QueueTimeDelayedExecution(Time.FrameStartTime + 2 * i, delegate
				{
					m_subsystemAudio.PlaySound(audio0, 1f, 0f, 0f, 0f);
				});
			}
			m_bgmStartCd = 6f;
			Time.QueueTimeDelayedExecution(Time.FrameStartTime + 6, delegate
			{
				PlayBgm(bgm);
			});
		}
		public void PlayBgm(string path)
		{
			if (SAGhoulsManager.IsBGMPlaying)
				return;
			SAGhoulsManager.IsBGMPlaying = true;
			m_bgmStopTime = null;
			m_bgmSound = m_subsystemAudio.CreateSound(path);
			m_bgmSound.IsLooped = true;
		}
		public void StopBgm()
		{
			SAGhoulsManager.IsBGMPlaying = false;
			m_bgmStopTime = BGMFadeOutDuration;
		}
		public void Draw(Camera camera, int drawOrder)
		{
			var array = new DynamicArray<ComponentBody>();
			m_subsystemBodies.FindBodiesAroundPoint(m_componentPlayer.ComponentBody.Position.XZ, MaxSpawnRange, array);
			if (array.Count <= 0)
				return;
			Color barColor = new(Color.DarkRed, 200);
			FlatBatch3D flatBatch = m_primitivesRenderer3D.FlatBatch(0, DepthStencilState.DepthRead, null, BlendState.AlphaBlend);
			foreach (var body in array)
			{
				Vector2 barSize = new(4f, 0.2f);
				ComponentSAGhouls componentSAGhouls = body.Entity.FindComponent<ComponentSAGhouls>();
				if (componentSAGhouls != null && componentSAGhouls.IsBoss && componentSAGhouls.IsAddedToProject)
				{
					float health = componentSAGhouls.m_componentCreature.ComponentHealth.Health;
					if (health <= 0)
						continue;
					m_bossLiving = true;
					Vector3 barCenter = body.Position + componentSAGhouls.BoxSize.Y * 1.1f * Vector3.UnitY;
					Vector3 forward = Vector3.Normalize(camera.ViewPosition - barCenter);
					Vector3 right = Vector3.Normalize(Vector3.Cross(Vector3.UnitY, forward));
					Vector3 up = Vector3.Normalize(Vector3.Cross(forward, right));

					for (int i = 0; i < 2; i++)
					{
						float border = 0.01f;
						Color color = i == 0 ? Color.Black : Color.White;
						Vector3 outer_0 = barCenter - barSize.X * 0.5f * right + barSize.Y * 0.5f * up;
						Vector3 outer_1 = barCenter + barSize.X * 0.5f * right + barSize.Y * 0.5f * up;
						Vector3 outer_2 = barCenter + barSize.X * 0.5f * right - barSize.Y * 0.5f * up;
						Vector3 outer_3 = barCenter - barSize.X * 0.5f * right - barSize.Y * 0.5f * up;

						Vector3 inner_0 = barCenter - (barSize.X * 0.5f - border) * right + (barSize.Y * 0.5f - border) * up;
						Vector3 inner_1 = barCenter + (barSize.X * 0.5f - border) * right + (barSize.Y * 0.5f - border) * up;
						Vector3 inner_2 = barCenter + (barSize.X * 0.5f - border) * right - (barSize.Y * 0.5f - border) * up;
						Vector3 inner_3 = barCenter - (barSize.X * 0.5f - border) * right - (barSize.Y * 0.5f - border) * up;

						flatBatch.QueueQuad(outer_0, outer_1, inner_1, inner_0, color);
						flatBatch.QueueQuad(inner_1, outer_1, outer_2, inner_2, color);
						flatBatch.QueueQuad(inner_3, inner_2, outer_2, outer_3, color);
						flatBatch.QueueQuad(outer_0, inner_0, inner_3, outer_3, color);
						barSize -= new Vector2(border * 2f);
					}

					Vector3 p0 = barCenter - barSize.X * 0.5f * health * right + barSize.Y * 0.5f * up;
					Vector3 p1 = barCenter + barSize.X * 0.5f * health * right + barSize.Y * 0.5f * up;
					Vector3 p2 = barCenter + barSize.X * 0.5f * health * right - barSize.Y * 0.5f * up;
					Vector3 p3 = barCenter - barSize.X * 0.5f * health * right - barSize.Y * 0.5f * up;
					flatBatch.QueueQuad(p0, p1, p2, p3, barColor);
				}
			}

			if (SoulsValue > 0.01f)
				m_componentScreenOverlays.DrawOverlay(camera, new Color(42, 9, 96), MathUtils.Saturate(2f * (SoulsValue - 0.5f)), SoulsValue);

			m_primitivesRenderer3D.Flush(camera.ViewProjectionMatrix);
		}
	}
}
